﻿using GameProtocol.Protocol;
using Google.Protobuf;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace GameLogic
{
    public class TCPClient : NetClient
    {
        Socket m_Socket;
        Socket m_ConnectedHandle;
        byte[] m_ReceiveData = new byte[1500];

        public override void Init(int receivePort, IPEndPoint endPoint)
        {
            base.Init(receivePort, endPoint);
            if (m_Socket != null)
            {
                m_Socket.Close();
            }
            m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            m_Socket.BeginConnect(endPoint, OnConnected, m_Socket);
        }

        public override string GetLocalIP()
        {
            var endPoint = (IPEndPoint)m_Socket.LocalEndPoint;
            return endPoint.Address.ToString();
        }
        protected override void Send(byte[] data, int length)
        {
            var sendResult = m_ConnectedHandle.Send(data, length, SocketFlags.None);
            if (sendResult > 0)
            {

            }
            else
            {
                UnityEngine.Debug.LogError("发送错误");
            }
        }
        byte[] m_DataBuffer = new byte[1024];
        public override void Send(GameProtocol.Protocol.CSMsgId id, byte[] data)
        {
            MessageContent content = new MessageContent();
            if (data != null)
                content.Data = ByteString.CopyFrom(data);
            content.MsgID = id;

            var length = GlobalFunction.PlusLengthHeadToByteArray(m_DataBuffer, content.ToByteArray());
            Send(m_DataBuffer, length);
        }
        public override void Handshake()
        {
            ConnectRqrData data = new ConnectRqrData();
            data.ConversationID = m_ConversationID;
            Send(CSMsgId.ConnectRqr, data.ToByteArray());
        }
        protected override void OnReceived(IPEndPoint ep, byte[] data, int offset, int length)
        {
            base.OnReceived(ep, data, offset, length);
            var msg = MessageContent.Parser.ParseFrom(data, offset, length);
            if (msg != null && m_ReceiveEvents.ContainsKey(msg.MsgID))
            {
                var subData = msg.Data.ToByteArray();
                var rspData = ConnectRspData.Parser.ParseFrom(subData);
                if (rspData != null && msg.MsgID == CSMsgId.ConnectRsp && !m_HasHandshake)
                {
                    m_HasHandshake = true;
                    UnityEngine.Debug.Log("服务器牵手成功！");
                }
                m_ReceiveEvents[msg.MsgID].Invoke((IPEndPoint)m_Socket.RemoteEndPoint, subData);
            }
        }
        void OnConnected(IAsyncResult result)
        {
            if (result.IsCompleted)
            {
                m_ConnectedHandle = (Socket)result.AsyncState;
                m_ConnectedHandle.EndConnect(result);
                Handshake();
                DoReceive();
                UnityEngine.Debug.Log("服务器连接成功, 尝试牵手");
            }
            else
            {
                UnityEngine.Debug.Log("服务器连接失败");
            }
        }

        async void DoReceive()
        {
            await Task.Run(() =>
            {
                if (m_ConnectedHandle.Connected)
                {
                    var length = m_ConnectedHandle.Receive(m_ReceiveData);

                    var curOffset = 0;
                    var curLength = length;
                    var packageLength = 0;
                    packageLength = BitConverter.ToUInt16(m_ReceiveData, curOffset);
                    while (curLength >= packageLength + 2)
                    {// 解决粘包问题
                        OnReceived(null, m_ReceiveData, curOffset + 2, packageLength);
                        curOffset += packageLength + 2;
                        curLength -= packageLength + 2;
                        packageLength = BitConverter.ToUInt16(m_ReceiveData, curOffset);
                    }
                }
            });
            DoReceive();
        }
    }
}
